package handler

import (
	"log"

	sms "git.oschina.net/fanbuchi/xgggh/sms/proto/sms"
	"git.oschina.net/fanbuchi/xgggh/utils/regular"
	"golang.org/x/net/context"
	_"git.oschina.net/fanbuchi/xgggh/sms/service"
	"git.oschina.net/fanbuchi/xgggh/sms/service"
	"fmt"
	"git.oschina.net/fanbuchi/xgggh/sms/model"
	"errors"
	"git.oschina.net/fanbuchi/xgggh/sms/db"
	"encoding/json"
	"strconv"
	"time"
	"regexp"
	"github.com/jinzhu/gorm"
	"git.oschina.net/fanbuchi/xgggh/utils/debug"
)
var template map[string]string = make (map[string]string)
var channel map[string]model.Channel= make (map[string]model.Channel)

func init() {
	template["login"]="您的登陆验证码是:%s【坤君科技】"
	template["invite"]="您的好友匿名评价了您,去看看吧http://t.cn/zrrser【坤君科技】"

		channel["luosimao"]=model.Channel{Name:"luosimao",
		ApiDomain:"http://sms-api.luosimao.com/v1/send.json",
		Account:"chengfukm",
		Org:"上海铁壳网络科技有限公司",
		Key:"e924eada8a507c5672fd4f6a339ba0e2",
		Secret:"",
	}
}


type Sms struct{
}

//创建验证码
//micro query com.xgggh.srv.sms Sms.Create '{"mobile":"15108280907","Template":"login","Channel":"luosimao"}'
func (e *Sms) Create(ctx context.Context, req *sms.CreateReq, rsp *sms.CreateRsp) error {
	//验证手机号码有是否有效
	matched,err:=regexp.MatchString(regular.MobileRegular,req.Mobile)
	log.Println("--->",req.Mobile,matched)
	if  !matched{
		return errors.New("无效手机账号")
	}

	//每天最多发送10次 每90s最多1次
	//短信验证码 5min内验证有效
	var maxCount=10;

	var smsList [] *model.Sms;
	now := time.Now()
	year, month, day := now.Date()
	today := time.Date(year, month, day, 0, 0, 0, 0, time.Local)

	err=db.Master().
		Unscoped().
		Where("mobile=?",req.Mobile).
		Where("template=?",req.Template).
		Where("created_at>=?",today).//today
		Order("id desc").
		Limit(maxCount+1).
		Find(&smsList).
		Error
	if smsList!=nil && len(smsList)>=maxCount {
		return errors.New("短信是要钱的,今天额度用完了!")
	}
	if smsList!=nil && len(smsList)>0 && smsList[0].CreatedAt.Add(90*time.Second).After(time.Now()) {
		return errors.New("短信是要钱的,请等等再发!")
	}

	code:= service.GenerateVerifyCode(req.Mobile)
	tmp:=template[req.Template]
	if tmp=="" {
		 return  errors.New("验证码模板错误")
	}
	resultSms:=fmt.Sprintf(tmp,code)

	if req.Channel==""{
		req.Channel="luosimao"
	}

	sms:=model.Sms{Mobile:req.Mobile,
		Template:resultSms,
		Code:code,
		TemplateType:"txl."+req.Template,
		ChannelId:req.Channel,
	}
	err=db.Master().Create(&sms).Error
	if err !=nil{
		return err
	}


	if !debug.Debug {
		channel:=channel[req.Channel]
		var sendVerify service.SendVerify
		sendVerify=service.LuoSiMaoSendVerify{Channel:&channel,Sms:&sms}
		result,err:=sendVerify.SendSms()

		if result!=nil {
			d:=SmsReult{}
			json.Unmarshal(result,&d)
			err=db.Master().Model(&sms).Update("result", strconv.Itoa(d.Error)+d.Msg+d.Hit).Error
		}
		return err
	}
	return err
}

type SmsReult struct {
	Error	int
	Msg     string
	Batch_id	string	//否	09-B0966DD4-FD28-43C3-94A8-F762B2269B72	批次号，管理中心开启状态推送后，请返回此参数用于接收状态回执的对应
	Hit	string	//否	年化收益	敏感词，error为-31时会出现
}


//micro query com.xgggh.srv.sms Sms.Validate '{"mobile":"15108280907","code":"110"}'

func (e *Sms) Validate(ctx context.Context, req *sms.ValidateReq, rsp *sms.ValidateRsp) error {
	fiveMin:=time.Now().Add(-5 * time.Minute)

	var sms model.Sms
	err:=db.Master().
		Where("mobile=?",req.Mobile).
		Where("created_at>=?",fiveMin).//today
		Order("id desc").
		First(&sms).
		Error
	if  sms.Code==req.Code {
		rsp.Ok=true
		//只允许验证一次
		db.Master().Delete(&sms)
	}else{
		return errors.New("验证码验证错误")
	}

	if err==gorm.ErrRecordNotFound {
		return errors.New("验证码验证错误")
	}
	return err
}

//micro query com.xgggh.srv.oauth2 AccountSrv.Query '{"id":10}'
func (e *Sms) Query(ctx context.Context, req *sms.QueryReq, rsp *sms.QueryRsp) error {
	return nil
}




func (e *Sms) Update(ctx context.Context, req *sms.UpdateReq, rsp *sms.UpdateRsp) error {
	return nil
}

func (e *Sms) Delete(ctx context.Context, req *sms.DeleteReq, rsp *sms.DeleteRsp) error {
	return nil
}

func (e *Sms) Search(ctx context.Context, req *sms.SearchReq, rsp *sms.SearchRsp) error {
	return nil
}

// Stream is a server side stream handler called via client.Stream or the generated client code
func (e *Sms) Stream(ctx context.Context, req *sms.StreamingRequest, stream sms.Sms_StreamStream) error {
	log.Printf("Received Example.Stream request with count: %d", req.Count)

	for i := 0; i < int(req.Count); i++ {
		log.Printf("Responding: %d", i)
		if err := stream.Send(&sms.StreamingResponse{
			Count: int64(i),
		}); err != nil {
			return err
		}
	}

	return nil
}

// PingPong is a bidirectional stream handler called via client.Stream or the generated client code
func (e *Sms) PingPong(ctx context.Context, stream sms.Sms_PingPongStream) error {
	for {
		req, err := stream.Recv()
		if err != nil {
			return err
		}
		log.Printf("Got ping %v", req.Stroke)
		if err := stream.Send(&sms.Pong{Stroke: req.Stroke}); err != nil {
			return err
		}
	}
}
